<!DOCTYPE html>
<html>
<head>
    <title>Physics Diagram - Molecule in a Box</title>
    <style>
        body {
            display: flex;
            justify-content: center;
            align-items: center;
            height: 100vh;
            margin: 0;
            background-color: #f0f0f0;
        }
        canvas {
            border: 1px solid #ccc;
            background-color: #ffffff;
        }
    </style>
</head>
<body>
    <canvas id="physicsCanvas" width="500" height="420"></canvas>
    <script>
        const canvas = document.getElementById('physicsCanvas');
        const ctx = canvas.getContext('2d');

        // --- Style setup ---
        ctx.strokeStyle = 'black';
        ctx.fillStyle = 'black';
        ctx.lineWidth = 1.5;
        ctx.font = '20px sans-serif';

        // --- Helper Functions ---
        function drawLine(p1, p2) {
            ctx.beginPath();
            ctx.moveTo(p1.x, p1.y);
            ctx.lineTo(p2.x, p2.y);
            ctx.stroke();
        }

        function drawArrow(fromX, fromY, toX, toY, headLength = 10) {
            const angle = Math.atan2(toY - fromY, toX - fromX);
            // Draw the line
            ctx.beginPath();
            ctx.moveTo(fromX, fromY);
            ctx.lineTo(toX, toY);
            ctx.stroke();
            // Draw the arrowhead
            ctx.beginPath();
            ctx.moveTo(toX, toY);
            ctx.lineTo(toX - headLength * Math.cos(angle - Math.PI / 6), toY - headLength * Math.sin(angle - Math.PI / 6));
            ctx.moveTo(toX, toY);
            ctx.lineTo(toX - headLength * Math.cos(angle + Math.PI / 6), toY - headLength * Math.sin(angle + Math.PI / 6));
            ctx.stroke();
        }

        function drawArrowhead(ctx, fromX, fromY, toX, toY, headLength = 8) {
             const angle = Math.atan2(toY - fromY, toX - fromX);
             ctx.beginPath();
             ctx.moveTo(toX, toY);
             ctx.lineTo(toX - headLength * Math.cos(angle - Math.PI / 6), toY - headLength * Math.sin(angle - Math.PI / 6));
             ctx.moveTo(toX, toY);
             ctx.lineTo(toX - headLength * Math.cos(angle + Math.PI / 6), toY - headLength * Math.sin(angle + Math.PI / 6));
             ctx.stroke();
        }

        // --- Cube Vertices Definition (Oblique Projection) ---
        const fbl = { x: 160, y: 300 }; // Front-Bottom-Left
        const fbr = { x: 320, y: 300 }; // Front-Bottom-Right
        const ftl = { x: 160, y: 140 }; // Front-Top-Left
        const ftr = { x: 320, y: 140 }; // Front-Top-Right

        const p_dx = 60;  // perspective depth in x
        const p_dy = -60; // perspective depth in y

        const bbl = { x: fbl.x + p_dx, y: fbl.y + p_dy }; // Back-Bottom-Left (hidden)
        const bbr = { x: fbr.x + p_dx, y: fbr.y + p_dy }; // Back-Bottom-Right
        const btl = { x: ftl.x + p_dx, y: ftl.y + p_dy }; // Back-Top-Left
        const btr = { x: ftr.x + p_dx, y: ftr.y + p_dy }; // Back-Top-Right

        // --- 1. Draw Shaded Face (Right Face) ---
        ctx.fillStyle = '#E0E0E0';
        ctx.beginPath();
        ctx.moveTo(ftr.x, ftr.y);
        ctx.lineTo(fbr.x, fbr.y);
        ctx.lineTo(bbr.x, bbr.y);
        ctx.lineTo(btr.x, btr.y);
        ctx.closePath();
        ctx.fill();
        ctx.strokeStyle = 'black';
        drawLine(ftr, fbr);
        drawLine(fbr, bbr);
        drawLine(bbr, btr);
        drawLine(btr, ftr);

        // --- 2. Draw Dashed (Hidden) Lines ---
        ctx.save();
        ctx.setLineDash([5, 5]);
        drawLine(fbl, bbl); // Bottom-left receding edge
        drawLine(btl, bbl); // Back-left vertical edge
        drawLine(bbr, bbl); // Back-bottom horizontal edge
        ctx.restore();

        // --- 3. Draw Solid (Visible) Lines ---
        drawLine(fbl, fbr); // Front-bottom
        drawLine(fbl, ftl); // Front-left
        drawLine(ftl, ftr); // Front-top
        drawLine(ftl, btl); // Top-left receding edge

        // --- 4. Draw Molecule and Velocity Vector ---
        const molecule_pos = { x: 240, y: 220 };
        const molecule_r = 7;

        // Molecule circle
        ctx.fillStyle = 'black';
        ctx.beginPath();
        ctx.arc(molecule_pos.x, molecule_pos.y, molecule_r, 0, 2 * Math.PI);
        ctx.fill();

        // Velocity arrow
        const u_start_x = molecule_pos.x + molecule_r;
        const u_end_x = u_start_x + 90;
        drawArrow(u_start_x, molecule_pos.y, u_end_x, molecule_pos.y, 8);

        // Velocity label 'u'
        ctx.font = 'italic 20px "Times New Roman"';
        ctx.textAlign = 'center';
        ctx.fillText('u', (u_start_x + u_end_x) / 2, molecule_pos.y - 12);

        // --- 5. Draw Labels ---
        // "molecule" label
        ctx.font = '20px sans-serif';
        ctx.textAlign = 'right';
        ctx.fillText('molecule', 150, 195);
        // Line from label to molecule
        ctx.beginPath();
        ctx.moveTo(155, 192);
        ctx.lineTo(molecule_pos.x - molecule_r, molecule_pos.y - molecule_r / 2);
        ctx.stroke();

        // "L" label
        const L_x_pos = btr.x + 40;
        // Dashed helper lines
        ctx.save();
        ctx.setLineDash([3, 3]);
        drawLine({x: btr.x, y: btr.y}, {x: L_x_pos, y: btr.y});
        drawLine({x: bbr.x, y: bbr.y}, {x: L_x_pos, y: bbr.y});
        ctx.restore();
        
        // Vertical line for L
        ctx.beginPath();
        ctx.moveTo(L_x_pos, btr.y);
        ctx.lineTo(L_x_pos, bbr.y);
        ctx.stroke();
        // Arrowheads
        drawArrowhead(ctx, L_x_pos, bbr.y, L_x_pos, btr.y); // pointing up
        drawArrowhead(ctx, L_x_pos, btr.y, L_x_pos, bbr.y); // pointing down

        // 'L' text
        ctx.font = 'italic 22px "Times New Roman"';
        ctx.textAlign = 'left';
        ctx.fillText('L', L_x_pos + 12, (btr.y + bbr.y) / 2 + 8);

        // "Fig. 3.1" label
        ctx.font = '20px sans-serif';
        ctx.textAlign = 'center';
        ctx.fillStyle = 'black';
        ctx.fillText('Fig. 3.1', canvas.width / 2, 380);

    </script>
</body>
</html>